#!/bin/bash

# ==============================================================================
# Huawei MCP Tools Installer Script
#
# Installs dependencies: Python, pip, Node.js, npm, Cherry Studio, uv, bun
# Supports running in Git Bash on Windows.
# ==============================================================================

# --- Configuration ---
PYTHON_VERSION="3.11.9"
PYTHON_INSTALLER_URL="https://mirrors.huaweicloud.com/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-amd64.exe"
PYTHON_INSTALLER_NAME="python-${PYTHON_VERSION}-amd64.exe"
GET_PIP_URL="https://bootstrap.pypa.io/get-pip.py"
PIP_MIRROR="https://mirrors.huaweicloud.com/repository/pypi/simple"

NODE_VERSION="16.7.0"
# Corrected URL based on specific version
NODE_INSTALLER_URL="https://mirrors.huaweicloud.com/nodejs/v${NODE_VERSION}/node-v${NODE_VERSION}-x64.msi"
NODE_INSTALLER_NAME="node-v${NODE_VERSION}-x64.msi"
NPM_MIRROR="https://mirrors.huaweicloud.com/npm/"

CHERRY_STUDIO_VERSION="1.2.3"
CHERRY_STUDIO_INSTALLER_URL="https://github.com/CherryHQ/cherry-studio/releases/download/v${CHERRY_STUDIO_VERSION}/Cherry-Studio-${CHERRY_STUDIO_VERSION}-x64-setup.exe"
CHERRY_STUDIO_INSTALLER_NAME="Cherry-Studio-${CHERRY_STUDIO_VERSION}-x64-setup.exe"
# Assume default install path for check: C:\Program Files\Cherry Studio
CHERRY_STUDIO_INSTALL_PATH="/c/Program Files/Cherry Studio/Cherry Studio.exe" # Git Bash path

UV_VERSION="0.6.14"
UV_INSTALLER_URL="https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-x86_64-pc-windows-msvc.zip"
UV_INSTALLER_NAME="uv-x86_64-pc-windows-msvc.zip"
UV_EXE_NAME="uv.exe"

BUN_VERSION="1.2.9"
BUN_INSTALLER_URL="https://github.com/oven-sh/bun/releases/download/bun-v${BUN_VERSION}/bun-windows-x64-baseline.zip"
BUN_INSTALLER_NAME="bun-windows-x64-baseline.zip"
BUN_EXE_NAME="bun.exe"

# Target directory for uv and bun
TARGET_BIN_DIR_WIN="C:\\Users\\${USERNAME}\\.cherrystudio\\bin"
TARGET_BIN_DIR_BASH="${USERPROFILE}/.cherrystudio/bin"

DOWNLOAD_DIR="./mcp_install_downloads"

# --- Helper Functions ---

# Print info message
info() {
    echo "[INFO] $1"
}

# Print error message and exit
error() {
    echo "[ERROR] $1" >&2
    # exit 1 # Optional: Exit on first error
}

# Check if a command exists
command_exists() {
    command -v "$1" &> /dev/null
}

# Ask user for confirmation to install
ask_install() {
    local software_name="$1"
    while true; do
        read -p "Do you want to install ${software_name}? (y/n): " yn
        case $yn in
            [Yy]* ) return 0;;
            [Nn]* ) info "Skipping installation of ${software_name}."; return 1;;
            * ) echo "Please answer yes or no.";;
        esac
    done
}

# Download a file
download_file() {
    local url="$1"
    local output_path="$2"
    info "Downloading ${output_path} from ${url}..."
    if curl -L -o "${output_path}" "${url}"; then
        info "Download successful: ${output_path}"
        return 0
    else
        error "Download failed: ${url}"
        return 1
    fi
}

# Add directory to User PATH environment variable persistently using registry
add_to_user_path() {
    local dir_to_add_win="$1"
    info "Adding ${dir_to_add_win} to User PATH..."

    # Read current User Path from Registry
    local current_path
    current_path=$(reg query "HKCU\\Environment" /v Path 2>/dev/null | grep 'Path' | sed 's/.*REG_SZ\s*//') || \
    current_path=$(reg query "HKCU\\Environment" /v Path 2>/dev/null | grep 'Path' | sed 's/.*REG_EXPAND_SZ\s*//')

    if [[ -z "$current_path" ]]; then
        info "User PATH environment variable not found or empty. Creating new one."
        local new_path="${dir_to_add_win}"
    elif [[ ";${current_path};" == *";${dir_to_add_win};"* ]]; then
        info "${dir_to_add_win} already exists in User PATH."
        return 0
    else
         # Append, ensuring no double semicolons if current_path ends with one
        [[ "${current_path}" == *";" ]] || current_path="${current_path};"
        local new_path="${current_path}${dir_to_add_win}"
    fi

    # Write updated Path to Registry
    # Using REG_EXPAND_SZ allows for variables like %SystemRoot%, though not strictly needed here
    if reg add "HKCU\\Environment" /v Path /t REG_EXPAND_SZ /d "${new_path}" /f &> /dev/null; then
        info "Successfully added ${dir_to_add_win} to User PATH in registry."
        info "Please restart your Git Bash or terminal session for PATH changes to take effect."
    else
        error "Failed to add ${dir_to_add_win} to User PATH in registry."
        error "You may need to add it manually: Control Panel -> System -> Advanced system settings -> Environment Variables"
        return 1
    fi
    # Broadcast the change (optional, may not work in all environments)
    # SendMessageTimeout HWND_BROADCAST WM_SETTINGCHANGE 0 "Environment" SMTO_NORMAL 1000 NULL
    # This is hard to do reliably from bash, skipping. User needs to restart shell.
}

# --- Installation Functions ---

install_python_and_pip() {
    info "--- Checking Python and Pip ---"
    local python_installed=false
    local pip_installed=false

    if command_exists python; then
        local version=$(python --version 2>&1)
        if [[ "$version" == *"Python 3"* ]]; then
            info "Python 3 already installed: $version"
            python_installed=true
        else
            info "Found Python, but it's not Python 3 ($version). Will attempt upgrade/install."
        fi
    else
        info "Python not found."
    fi

    if ! $python_installed; then
        if ask_install "Python ${PYTHON_VERSION}"; then
            download_file "${PYTHON_INSTALLER_URL}" "${DOWNLOAD_DIR}/${PYTHON_INSTALLER_NAME}" || return 1
            info "Installing Python ${PYTHON_VERSION} silently..."
            # /quiet: Silent mode
            # PrependPath=1: Add Python to PATH
            # InstallAllUsers=1: Install for all users (requires elevation potentially) or InstallAllUsers=0 for current user
            # TargetDir=...: Optional specific target directory
            if "${DOWNLOAD_DIR}/${PYTHON_INSTALLER_NAME}" /quiet PrependPath=1 InstallAllUsers=1; then
                 info "Python ${PYTHON_VERSION} installation successful."
                 info "Please restart your Git Bash or terminal session for PATH changes to take effect."
                 python_installed=true # Assume success for pip check below
            else
                 error "Python installation failed."
                 return 1
            fi
        else
             return 1 # Skipped Python, can't install pip either
        fi
    fi

    # Check pip
    if command_exists pip; then
         info "pip already installed: $(pip --version)"
         pip_installed=true
    else
         info "pip not found."
         if $python_installed; then # Only try installing pip if Python is available
             if ask_install "pip"; then
                 download_file "${GET_PIP_URL}" "${DOWNLOAD_DIR}/get-pip.py" || return 1
                 info "Installing pip using get-pip.py..."
                 if python "${DOWNLOAD_DIR}/get-pip.py"; then
                     info "pip installation successful."
                     pip_installed=true
                 else
                     error "pip installation failed."
                     return 1
                 fi
             fi
         else
             info "Cannot install pip because Python installation was skipped or failed."
         fi
    fi

    # Configure pip mirror
    if $pip_installed; then
        info "Checking pip mirror configuration..."
        local current_mirror
        current_mirror=$(pip config get global.index-url 2>/dev/null)
        if [[ -n "$current_mirror" ]]; then
            info "Current pip mirror: ${current_mirror}"
            if [[ "$current_mirror" != "$PIP_MIRROR" ]]; then
                 read -p "Found existing pip mirror. Do you want to change it to Huawei mirror (${PIP_MIRROR})? (y/n): " yn_mirror
                 if [[ "$yn_mirror" == [Yy]* ]]; then
                     info "Setting pip mirror to ${PIP_MIRROR}..."
                     pip config set global.index-url "${PIP_MIRROR}"
                 fi
            fi
        else
            info "No pip mirror configured."
            read -p "Do you want to configure Huawei pip mirror (${PIP_MIRROR})? (y/n): " yn_mirror
            if [[ "$yn_mirror" == [Yy]* ]]; then
                info "Setting pip mirror to ${PIP_MIRROR}..."
                pip config set global.index-url "${PIP_MIRROR}"
            fi
        fi
    fi
    info "--- Python and Pip check finished ---"
}

install_nodejs_and_npm() {
    info "--- Checking Node.js and npm ---"
    local node_installed=false

    if command_exists node; then
        info "Node.js already installed: $(node -v)"
        node_installed=true
    else
        info "Node.js not found."
    fi

    if ! $node_installed; then
        if ask_install "Node.js ${NODE_VERSION}"; then
            download_file "${NODE_INSTALLER_URL}" "${DOWNLOAD_DIR}/${NODE_INSTALLER_NAME}" || return 1
            info "Installing Node.js ${NODE_VERSION} silently..."
            # /i: Install
            # /qn: Quiet, no UI
            if msiexec /i "${DOWNLOAD_DIR}/${NODE_INSTALLER_NAME}" /qn; then
                 info "Node.js ${NODE_VERSION} installation successful."
                 info "Please restart your Git Bash or terminal session for PATH changes to take effect."
                 node_installed=true # Assume success for npm check below
            else
                 error "Node.js installation failed."
                 return 1
            fi
        fi
    fi

    # Check npm (comes with Node.js) and configure mirror
    if $node_installed && command_exists npm; then
        info "npm version: $(npm -v)"
        info "Checking npm mirror configuration..."
        local current_registry
        current_registry=$(npm config get registry 2>/dev/null)

        if [[ -n "$current_registry" ]]; then
            info "Current npm registry: ${current_registry}"
             if [[ "$current_registry" != "$NPM_MIRROR" ]]; then
                 read -p "Found existing npm registry. Do you want to change it to Huawei mirror (${NPM_MIRROR})? (y/n): " yn_mirror
                 if [[ "$yn_mirror" == [Yy]* ]]; then
                     info "Setting npm registry to ${NPM_MIRROR}..."
                     npm config set registry "${NPM_MIRROR}"
                 fi
             fi
        else
            info "No npm registry configured."
            read -p "Do you want to configure Huawei npm registry (${NPM_MIRROR})? (y/n): " yn_mirror
            if [[ "$yn_mirror" == [Yy]* ]]; then
                 info "Setting npm registry to ${NPM_MIRROR}..."
                 npm config set registry "${NPM_MIRROR}"
            fi
        fi
    elif $node_installed; then
        error "Node.js seems installed, but npm command not found. Please check Node.js installation."
    else
         info "npm check skipped because Node.js installation was skipped or failed."
    fi
    info "--- Node.js and npm check finished ---"
}

install_cherry_studio() {
    info "--- Checking Cherry Studio ---"
    # Basic check: does the default installation executable exist?
    if [[ -f "${CHERRY_STUDIO_INSTALL_PATH}" ]]; then
        # Getting version from exe is complex, just confirm presence
        info "Cherry Studio installation directory found at '${CHERRY_STUDIO_INSTALL_PATH}'. Assuming installed."
        # Optionally, try running "${CHERRY_STUDIO_INSTALL_PATH}" --version if that works
    else
        info "Cherry Studio not found (checked default path: ${CHERRY_STUDIO_INSTALL_PATH})."
        if ask_install "Cherry Studio ${CHERRY_STUDIO_VERSION}"; then
            download_file "${CHERRY_STUDIO_INSTALLER_URL}" "${DOWNLOAD_DIR}/${CHERRY_STUDIO_INSTALLER_NAME}" || return 1
            info "Installing Cherry Studio ${CHERRY_STUDIO_VERSION} silently..."
            # Common silent flags for setups: /S, /SILENT, /VERYSILENT
            # Trying /S first
            if "${DOWNLOAD_DIR}/${CHERRY_STUDIO_INSTALLER_NAME}" /S; then
                 info "Cherry Studio ${CHERRY_STUDIO_VERSION} installation successful."
                 # Check again if the file exists now
                 if [[ -f "${CHERRY_STUDIO_INSTALL_PATH}" ]]; then
                     info "Installation confirmed at ${CHERRY_STUDIO_INSTALL_PATH}"
                 else
                     info "Installation command finished, but couldn't verify executable at default path. Check installation manually."
                 fi
            else
                 error "Cherry Studio installation failed. Try running installer manually: ${DOWNLOAD_DIR}/${CHERRY_STUDIO_INSTALLER_NAME}"
                 return 1
            fi
        fi
    fi
    info "--- Cherry Studio check finished ---"
}

# Install tools like uv and bun into a specific directory
install_tool_to_bin() {
    local tool_name="$1"
    local tool_version="$2"
    local tool_url="$3"
    local tool_zip_name="$4"
    local tool_exe_name="$5"
    local target_dir_bash="$6"
    local target_dir_win="$7"
    local target_exe_path_bash="${target_dir_bash}/${tool_exe_name}"

    info "--- Checking ${tool_name} ---"

    # Ensure target directory exists
    mkdir -p "${target_dir_bash}"

    # Check if executable exists in target directory
    if [[ -f "${target_exe_path_bash}" ]]; then
         # Try getting version if command is in PATH or we use full path
         local version_cmd_output
         if command_exists "${tool_name}"; then
             version_cmd_output=$("${tool_name}" --version 2>&1)
         elif [[ -x "${target_exe_path_bash}" ]]; then
              version_cmd_output=$("${target_exe_path_bash}" --version 2>&1)
         fi

         if [[ -n "$version_cmd_output" ]]; then
             info "${tool_name} found: ${version_cmd_output}"
         else
             info "${tool_name} executable found at ${target_exe_path_bash}, but couldn't get version."
         fi

         # Check if the target dir is in PATH
         if [[ ":$PATH:" != *":${target_dir_bash}:"* ]]; then
              info "WARNING: ${target_dir_bash} not found in current session PATH. Adding to User PATH..."
              add_to_user_path "${target_dir_win}"
         fi

    else
        info "${tool_name} not found in ${target_dir_bash}."
        if ask_install "${tool_name} ${tool_version}"; then
            download_file "${tool_url}" "${DOWNLOAD_DIR}/${tool_zip_name}" || return 1
            info "Extracting ${tool_name} from ${tool_zip_name}..."

            # Unzip the executable to the target directory
            # Flags: -o (overwrite), -j (junk paths, extract only files), -d (destination)
            # Need to know the structure of the zip. Assume exe is at the root or in a known subdir.
            # Trying -j first assuming uv.exe / bun.exe is at the root of the zip.
            if unzip -oj "${DOWNLOAD_DIR}/${tool_zip_name}" "${tool_exe_name}" -d "${target_dir_bash}"; then
                 info "${tool_name} extracted successfully to ${target_dir_bash}."
                 chmod +x "${target_exe_path_bash}" # Ensure executable permission

                 # Add target dir to PATH
                 add_to_user_path "${target_dir_win}"

                 # Verify installation
                 if [[ -f "${target_exe_path_bash}" ]]; then
                     info "${tool_name} installation successful. Version: $(${target_exe_path_bash} --version 2>&1)"
                 else
                     error "${tool_name} installation failed: Executable not found after extraction."
                     return 1
                 fi
            else
                 error "Failed to extract ${tool_name} from ${tool_zip_name}."
                 error "Check if unzip command is available and the zip file structure."
                 return 1
            fi
        fi
    fi
    info "--- ${tool_name} check finished ---"

}


# --- Main Script ---

# Create download directory
mkdir -p "${DOWNLOAD_DIR}"

# Install components
install_python_and_pip
install_nodejs_and_npm
install_cherry_studio
install_tool_to_bin "uv" "${UV_VERSION}" "${UV_INSTALLER_URL}" "${UV_INSTALLER_NAME}" "${UV_EXE_NAME}" "${TARGET_BIN_DIR_BASH}" "${TARGET_BIN_DIR_WIN}"
install_tool_to_bin "bun" "${BUN_VERSION}" "${BUN_INSTALLER_URL}" "${BUN_INSTALLER_NAME}" "${BUN_EXE_NAME}" "${TARGET_BIN_DIR_BASH}" "${TARGET_BIN_DIR_WIN}"


info "--- Installation Script Finished ---"
info "Remember to restart your Git Bash or terminal session for all PATH changes to take full effect."
# Optional: Clean up downloads
# read -p "Do you want to remove downloaded installers from ${DOWNLOAD_DIR}? (y/n): " yn_clean
# if [[ "$yn_clean" == [Yy]* ]]; then
#    rm -rf "${DOWNLOAD_DIR}"
#    info "Download directory removed."
# fi

exit 0
